use crate::error::Result;
use crate::types::Value;

/// A single row of data from a query result
#[derive(Debug, Clone)]
pub struct Row {
    /// 存储行中的数据值集合
    pub data: Vec<crate::types::Value>,
}

impl Row {
    /// Create a new row with the given values
    pub fn new(values: Vec<crate::types::Value>) -> Self {
        Self { data: values }
    }

    /// Get a value by index
    pub fn get<T>(&self, index: usize) -> Result<T>
    where
        T: TryFrom<Value>,
        T::Error: Into<crate::error::VerticaError>,
    {
        if index >= self.data.len() {
            return Err(crate::error::VerticaError::Query(format!("Index {} out of bounds (row has {} columns)", index, self.data.len())));
        }
        let value = &self.data[index];
        T::try_from(value.clone()).map_err(|e| e.into())
    }

    /// Get the number of columns in this row
    pub fn len(&self) -> usize {
        self.data.len()
    }

    /// Check if this row has no columns
    pub fn is_empty(&self) -> bool {
        self.data.is_empty()
    }

    /// Get all values in this row
    pub fn values(&self) -> &[crate::types::Value] {
        &self.data
    }
}

/// A collection of rows from a query result
#[derive(Debug, Clone)]
pub struct Rows {
    rows: Vec<Row>,
}

impl Rows {
    /// Create a new collection of rows
    pub fn new(rows: Vec<Row>) -> Self {
        Self { rows }
    }

    /// Get the number of rows
    pub fn len(&self) -> usize {
        self.rows.len()
    }

    /// Check if there are no rows
    pub fn is_empty(&self) -> bool {
        self.rows.is_empty()
    }

    /// Get the first row
    pub fn first(&self) -> Option<&Row> {
        self.rows.first()
    }

    /// Get an iterator over the rows
    pub fn iter(&self) -> std::slice::Iter<'_, Row> {
        self.rows.iter()
    }
}

impl IntoIterator for Rows {
    type Item = Row;
    type IntoIter = std::vec::IntoIter<Row>;

    fn into_iter(self) -> Self::IntoIter {
        self.rows.into_iter()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::types::Value;

    #[test]
    fn test_row_creation() {
        let values = vec![Value::Int(42), Value::String("hello".to_string())];
        let row = Row::new(values);
        assert_eq!(row.len(), 2);
        assert!(!row.is_empty());
    }

    #[test]
    fn test_row_get_by_index() {
        let values = vec![Value::Int(42), Value::String("hello".to_string())];
        let row = Row::new(values);
        
        let int_val: i32 = row.get(0).unwrap();
        assert_eq!(int_val, 42);
        
        let string_val: String = row.get(1).unwrap();
        assert_eq!(string_val, "hello");
    }

    #[test]
    fn test_rows_creation() {
        let row1 = Row::new(vec![Value::Int(1)]);
        let row2 = Row::new(vec![Value::Int(2)]);
        let rows = Rows::new(vec![row1, row2]);
        
        assert_eq!(rows.len(), 2);
        assert!(!rows.is_empty());
    }

    #[test]
    fn test_row_get_by_name() {
        // This test demonstrates how to get values by column name
        // In a real implementation, you would have column names available
        let values = vec![Value::Int(42), Value::String("hello".to_string())];
        let row = Row::new(values);
        
        // For now, we use index-based access
        let int_val: i32 = row.get(0).unwrap();
        assert_eq!(int_val, 42);
    }
}